﻿using System;
using Newtonsoft.Json;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Portfolios.BL.Exceptions;
using Sustainalytics.Portfolios.BL.Validators;
using Sustainalytics.Replication.Publisher;
using Sustainalytics.Utils;
using System.Collections.Generic;

namespace Sustainalytics.Portfolios.BL
{


    public interface IPortfolioDeleteHandler
    {
        void DeletePortfolio(Guid id, PortfolioUserClaims userClaims);
    }

    public class PortfolioDeleteHandler : IPortfolioDeleteHandler
    {
        private readonly IRepositoryCollection<Portfolio> _portfolioRepository;

        private readonly IRepositoryCollection<Portfolio> _systemPortfolioRepository;

        private readonly IRepositoryCollection<PortfolioDetails> _portfolioDetailsRepository;

        private readonly IRepositoryCollection<PortfolioUserInput> _securitiesUserInputRepository;

        private readonly IScreeningToolFilterManager _screeningToolFilterManager;

        private readonly ISubscribeToPortfolioManagement _subscriptionsManagement;

        private readonly ServiceBusPublisher _serviceBusPublisher;

        public PortfolioDeleteHandler(
            PortfolioTypeCollection<Portfolio> portfolioCollection,
            IRepositoryCollection<PortfolioDetails> portfolioDetailsRepository,
            IRepositoryCollection<PortfolioUserInput> securitiesUserInputRepository,
            IScreeningToolFilterManager screeningToolFilterManager,
            ISubscribeToPortfolioManagement subscriptionsManagement,
            ServiceBusPublisher serviceBusPublisher)
        {
            this._securitiesUserInputRepository = securitiesUserInputRepository;
            this._portfolioRepository = portfolioCollection.ClientCollection;
            this._systemPortfolioRepository = portfolioCollection.SystemCollections;
            this._portfolioDetailsRepository = portfolioDetailsRepository;
            this._screeningToolFilterManager = screeningToolFilterManager;
            this._subscriptionsManagement = subscriptionsManagement;
            this._serviceBusPublisher = serviceBusPublisher;
        }

        public void DeletePortfolio(Guid id, PortfolioUserClaims userClaims)
        {
            Portfolio portfolio;
            bool isCustom;
            if ((portfolio = this._portfolioRepository.Read(id)) != null)
            {
                isCustom = true;
            }
            else
            {
                portfolio = this._systemPortfolioRepository.Read(id);
                isCustom = false;
            }

            if (!PortfolioValidator.Write().IsValid(portfolio, userClaims))
            {
                throw new PortfolioDeleteUnauthorizedException();
            }

            this._subscriptionsManagement.DeleteSubscriptionToPortfolio(portfolio.Id);

            // update all filters
            this._screeningToolFilterManager.RemovePortfolioFromScreeningToolFilters(portfolio.Id);

            if (isCustom)
            {
                this._portfolioDetailsRepository.DeleteWhere(p => p.PortfolioId == portfolio.Id);
                _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(id), ReplicationUtils.EntityType.PortfolioDetails, ReplicationUtils.Operation.DeleteWhereByPortfolioId);

                this._securitiesUserInputRepository.DeleteWhere(p => p.PortfolioId == portfolio.Id);
                _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(id), ReplicationUtils.EntityType.PortfolioUserInput, ReplicationUtils.Operation.DeleteWhereByPortfolioId);

                this._portfolioRepository.Delete(id);
                _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(id), ReplicationUtils.EntityType.Portfolio, ReplicationUtils.Operation.Delete);
            }
            else
            {
                this._systemPortfolioRepository.Delete(id);
                _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(id), ReplicationUtils.EntityType.Portfolio, ReplicationUtils.Operation.Delete, ReplicationUtils.ConnectionStringType.ClientDW);
            }

        }
    }
}
